package com.mmz.spring.aop.framework;



import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import com.mmz.spring.aop.Advice;
import com.mmz.spring.aop.support.Advisor;
import com.mmz.spring.aop.support.DefaultPointcutAdvisor;
import com.mmz.spring.beans.factory.BeanFactory;
import com.mmz.spring.beans.factory.FactoryBean;
import com.mmz.spring.beans.factory.config.BeanFactoryAware;

public class ProxyFactoryBean extends ProxyCreatorSupport implements BeanFactoryAware,FactoryBean<Object> {

	private String[] interceptorNames;
	
	private transient BeanFactory beanFactory;
	
	// 标志位，当前目标对象的拦截器链是否已经初始化
	private boolean advisorChainInitialized = false;
	
	private List<Advisor> advisors = new LinkedList<Advisor>();
	
	private boolean singleton = true;
	
	// 这个相当于是判断使用cglib还是jdk动态代理生成代理对象标志
	private boolean autodetectInterfaces = true;
	
	// 代理类需要实现的接口，主要是动态代理的方式需要
	private List<Class<?>> interfaces = new ArrayList<Class<?>>();
	
	private transient ClassLoader proxyClassLoader = Thread.currentThread().getContextClassLoader();
	
	
	
	
	public ProxyFactoryBean(String... interceptorNames) {
		super();
		this.interceptorNames = interceptorNames;
	}
	
	public ProxyFactoryBean() {
		super();
		
	}

	// 单例代理对象的缓存，生成一次后则存储在此
	private Object singletonInstance;
	
	public void setBeanFactory(BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		
	}

	
	/**
	 * 核心方法，通过factorybean的特性包装目标对象，然后ioc获取
	 * factorybean时，调用该方法返回代理对象
	 * @throws Exception 
	 * */
	public Object getObject() throws Exception {
		initializeAdvisorChain();
		if (isSingleton()) {
			return getSingletonInstance();
		}
		return null;
	}
	
	private synchronized Object getSingletonInstance() {
		if (this.singletonInstance == null) {
			 // this.targetSource = freshTargetSource();
			if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
				// Rely on AOP infrastructure to tell us what interfaces to proxy.
				Class<?> targetClass = getTargetClass();
				if (targetClass == null) {
					throw new RuntimeException("目标class不能为空");
				}
				setInterfaces(getAllInterfacesForClass(targetClass, this.proxyClassLoader));
			}
			// 重头戏，真正的调用代理对象工厂生成代理对象
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}
	
	/**
	 * 递归获取目标对象的所有接口
	 * */
	public Class<?>[] getAllInterfacesForClass(Class<?> clazz, ClassLoader classLoader){
		Set<Class<?>> set = getAllInterfacesForClassAsSet(clazz,classLoader);
		return set.toArray(new Class<?>[set.size()]);
	}
	
	protected  Set<Class<?>>  getAllInterfacesForClassAsSet(Class<?> clazz, ClassLoader classLoader) {
		
		if (clazz.isInterface()) {
			return  Collections.<Class<?>>singleton(clazz);
		}
		Set<Class<?>> interfaces = new LinkedHashSet<Class<?>>();
		while (clazz != null) {
			Class<?>[] ifcs = clazz.getInterfaces();
			for (Class<?> ifc : ifcs) {
				interfaces.addAll(getAllInterfacesForClassAsSet(ifc, classLoader));
			}
			clazz = clazz.getSuperclass();
		}
		return interfaces;
	}
	/**
	 * 调用代理对象的getProxy,
	 * @param proxyClassLoader 默认的classloader
	 * */
	protected Object getProxy(AopProxy aopProxy) {
		return aopProxy.getProxy(this.proxyClassLoader);
	}
	
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return true;
	}
	
	private synchronized void initializeAdvisorChain() throws Exception {
		if (this.advisorChainInitialized) {
			return;
		}
		if (this.interceptorNames.length>0) {
			if (this.beanFactory == null) {
				throw new RuntimeException("No BeanFactory available anymore (probably due to serialization) " +
						"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
			}

			for (String name : this.interceptorNames) {
				
					Object advice = null;
					if (this.singleton) {
						// 通过ioc获取定义的advisor
						advice = this.beanFactory.getBean(name);
					}
//					else {
//						// It's a prototype Advice or Advisor: replace with a prototype.
//						// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
//						advice = new PrototypePlaceholderAdvisor(name);
//					}
					this.advisors.add(wrap(advice));
					
				}
			this.setAdvisorArray(this.advisors.toArray(new Advisor[this.advisors.size()]));
			
		}
		// 通知器(拦截器)链初始化已完成
		this.advisorChainInitialized = true;
		
	}
	
	public void setInterceptorNames(String...interceptorNames) {
		this.interceptorNames = interceptorNames;
	}


	private Advisor wrap(Object adviceObject){
		if(adviceObject instanceof Advisor){
			return (Advisor)adviceObject;
		}
		if(adviceObject instanceof Advice){
			return new DefaultPointcutAdvisor((Advice) adviceObject);
		}
		throw new RuntimeException("未定义的拦截器类型 "+adviceObject);
	}

}
